#pragma once
#ifndef __NSIS_API_H__
#define __NSIS_API_H__

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus


// Starting with NSIS 2.42, you can check the version of the plugin API in exec_flags->plugin_api_version
// The format is 0xXXXXYYYY where X is the major version and Y is the minor version (MAKELONG(y,x))
// When doing version checks, always remember to use >=, ex: if (pX->exec_flags->plugin_api_version >= NSISPIAPIVER_1_0) {}

#define NSISPIAPIVER_1_0 0x00010000
#define NSISPIAPIVER_CURR NSISPIAPIVER_1_0

// NSIS Plug-In Callback Messages
enum NSPIM
{
	NSPIM_UNLOAD,    // This is the last message a plugin gets, do final cleanup
	NSPIM_GUIUNLOAD, // Called after .onGUIEnd
};

// Prototype for callbacks registered with extra_parameters->RegisterPluginCallback()
// Return NULL for unknown messages
// Should always be __cdecl for future expansion possibilities
typedef UINT_PTR(*NSISPLUGINCALLBACK)(enum NSPIM);

// extra_parameters data structure containing other interesting stuff
// besides the stack, variables and HWND passed on to plug-ins.
typedef struct
{
	int autoclose;          // SetAutoClose
	int all_user_var;       // SetShellVarContext: User context = 0, Machine context = 1
	int exec_error;         // IfErrors/ClearErrors/SetErrors
	int abort;              // IfAbort
	int exec_reboot;        // IfRebootFlag/SetRebootFlag (NSIS_SUPPORT_REBOOT)
	int reboot_called;      // NSIS_SUPPORT_REBOOT
	int XXX_cur_insttype;   // Deprecated
	int plugin_api_version; // Plug-in ABI. See NSISPIAPIVER_CURR (Note: used to be XXX_insttype_changed)
	int silent;             // IfSilent/SetSilent (NSIS_CONFIG_SILENT_SUPPORT)
	int instdir_error;      // GetInstDirError
	int rtl;                // IfRtlLanguage: 1 if $LANGUAGE is a RTL language
	int errlvl;             // SetErrorLevel
	int alter_reg_view;     // SetRegView: Default View = 0, Alternative View = (sizeof(void*) > 4 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY)
	int status_update;      // SetDetailsPrint
} exec_flags_t;

#ifndef NSISCALL
#  define NSISCALL WINAPI
#endif
#if !defined(_WIN32) && !defined(LPTSTR)
#  define LPTSTR TCHAR*
#endif

typedef struct {
	exec_flags_t *exec_flags;
	int (NSISCALL *ExecuteCodeSegment)(int, HWND);
	void (NSISCALL *validate_filename)(LPTSTR);
	int (NSISCALL *RegisterPluginCallback)(HMODULE, NSISPLUGINCALLBACK); // returns 0 on success, 1 if already registered and < 0 on errors
} extra_parameters;

// Definitions for page showing plug-ins
// See Ui.c to understand better how they're used

// sent to the outer window to tell it to go to the next inner window
#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8)

// custom pages should send this message to let NSIS know they're ready
#define WM_NOTIFY_CUSTOM_READY (WM_USER+0xd)

// sent as wParam with WM_NOTIFY_OUTER_NEXT when user cancels - heed its warning
#define NOTIFY_BYE_BYE 'x'


#define EXDLL_INIT()           {  \
        g_stringsize = string_size; \
        g_stacktop = stacktop;      \
        g_variables = variables;}

typedef struct _stack_t {
	struct _stack_t *next;
	TCHAR text[1];
} stack_t;

enum
{
	INST_0,         // $0
	INST_1,         // $1
	INST_2,         // $2
	INST_3,         // $3
	INST_4,         // $4
	INST_5,         // $5
	INST_6,         // $6
	INST_7,         // $7
	INST_8,         // $8
	INST_9,         // $9
	INST_R0,        // $R0
	INST_R1,        // $R1
	INST_R2,        // $R2
	INST_R3,        // $R3
	INST_R4,        // $R4
	INST_R5,        // $R5
	INST_R6,        // $R6
	INST_R7,        // $R7
	INST_R8,        // $R8
	INST_R9,        // $R9
	INST_CMDLINE,   // $CMDLINE
	INST_INSTDIR,   // $INSTDIR
	INST_OUTDIR,    // $OUTDIR
	INST_EXEDIR,    // $EXEDIR
	INST_LANG,      // $LANGUAGE
	__INST_LAST
};

extern unsigned int g_stringsize;
extern stack_t **g_stacktop;
extern TCHAR *g_variables;
extern extra_parameters *g_extraparameters;

void NSISCALL PushString(LPTSTR str);

int NSISCALL PopString(LPTSTR str);

void NSISCALL PushInt(long value);

int NSISCALL PopInt();

LPTSTR  NSISCALL GetUserVariable(int varnum);

void NSISCALL SetUserVariable(int varnum, LPTSTR var);


#ifdef __cplusplus
}
#endif // __cplusplus


#endif // !__NSIS_API_H__
